import logging
from datetime import datetime, date, time
from common.timeutil import get_interval_end_pair
from datetime import timedelta
from django.conf import settings
from common.mg_core.mg import get_report_template, insert_or_update, MONGODB
from common.es_core.report_creator import UserReportCreator
from common.es_core.user_filter import UserFilter
from .const import WITHDRAW_SUB_TYPE, CHN_DEVICE_TYPE

_LOGGER = logging.getLogger(__name__)


def get_pay_type_list():
    return WITHDRAW_SUB_TYPE


def _get_graph_report_mongodb_group_by_query_dct(target_event, chn_list=None):
    group_by_query_dct = {'$group': {'_id': "$hour"}}
    group_by_template = {
        'recharge': {"key": "${}recharge_price.sum", "multiple": settings.PLATFORM_AMOUNT_ADJUST_RATE},
        'withdraw': {"key": "${}withdraw_price.sum", "multiple": settings.PLATFORM_AMOUNT_ADJUST_RATE},
        'bet': {"key": "${}bet_order_bet_amount.sum", "multiple": settings.PLATFORM_AMOUNT_ADJUST_RATE},
        'profit': {"key": "${}bet_order_profit.sum", "multiple": settings.PLATFORM_AMOUNT_ADJUST_RATE},
        'active': {'key': "${}uv"},
        'register': {'key': "${}uv"},
        'bind': {'key': "${}uv"},
        'recharge_user': {'key': "${}uv"},
        'new_recharge_user': {"key": '$groups_data._is_new_user.data.1.{}uv'},
        'new_recharge': {"key": '$groups_data._is_new_user.data.1.{}recharge_price.sum',
                         "multiple": settings.PLATFORM_AMOUNT_ADJUST_RATE}
    }
    assert target_event in group_by_template
    key, multiple_rate = group_by_template[target_event]['key'], group_by_template[target_event].get('multiple')
    if chn_list:
        assert isinstance(chn_list, list), '传参错误'
        query_form = {"$add": []}
        for chn in chn_list:
            query_form['$add'].append({'$ifNull': [key.format('groups_data._chn.data.{}.data.').format(chn), 0]})
        group_by_query_dct['$group']['target'] = {'$sum': query_form}
    else:
        group_by_query_dct['$group']['target'] = {"$sum": key.format('data.')}
    return group_by_query_dct


def op_graph_report_handler(merchant_name, target_event, chn_list=None):
    """
    :param merchant_name: 商户名
    :param target_event: 事件对象
    :param chn_list: 渠道列過濾條件
    :return:
    """
    assert merchant_name in settings.DWC_INDEX + settings.CP_INDEX
    report = {'graph_data': {}}
    if target_event in ('bet', 'profit',):
        condition = {'event_id': 'bet_order'}
    elif target_event in ('recharge', 'recharge_user', 'new_recharge_user', 'new_recharge'):
        condition = {'event_id': 'recharge'}
    else:
        condition = {'event_id': target_event}
    group_by_query_dct = _get_graph_report_mongodb_group_by_query_dct(target_event, chn_list)
    for key, start_delta, end_delta in (('today', 0, 0), ('yesterday', 1, 1),
                                        ('last_3', 3, 1), ('last_week', 7, 1),):
        report['graph_data'][key] = []
        day = datetime.combine(date.today(), time.min) - timedelta(days=start_delta)
        day_end = datetime.combine(date.today(), time.min) + timedelta(days=1 - end_delta)
        condition['base_time'] = {'$gte': day, '$lt': day_end}
        event_data = MONGODB[merchant_name].hour.aggregate([
            {'$match': condition},
            group_by_query_dct,
            {'$sort': {'_id': 1}}
        ])
        target = 0
        for item in event_data:
            target += item['target'] / (start_delta - end_delta + 1)
            if target_event == 'active':
                target -= 1 if target > 0 else 0  # 扣除用戶id為"1“之用戶
            report['graph_data'][key].append(target)
    return report


def op_report_handler(interval_type, base_time, last_window, event_name, event_rule, index):
    """
    :param interval_type: 报表时间单位
    :param base_time: 报表时间
    :param last_window: 时间段偏移值
    :param event_name: 报表名
    :param event_rule: 报表配置
    :param index: 商户索引名
    :return: None
    """
    start_time, end_time = get_interval_end_pair(interval_type, base_time, last_window)
    collection = '_'.join(['op', event_name, 'report'])
    report_template = get_report_template(start_time, interval_type)
    report_template.update(
        UserReportCreator.create_user_report(start_time=start_time, end_time=end_time,
                                             event_rule=event_rule, index=index)
    )
    insert_or_update(report_template, database=index, collection=collection)


def op_group_by_report_handler(interval_type, base_time, last_window, event_name, event_rule, index,
                               disable_global_aggregate=None):
    """
    :param interval_type: 报表时间单位
    :param base_time: 报表时间
    :param last_window: 时间段偏移值
    :param event_name: 报表名
    :param event_rule: 报表配置
    :param index: 商户索引名
    :param disable_global_aggregate: 是否关闭全局聚合
    :return: None
    """
    start_time, end_time = get_interval_end_pair(interval_type, base_time, last_window)
    day = str(start_time).split(' ')[0] if interval_type.value == 'day' else str(start_time).split(':')[0]
    collection = '_'.join(['op', event_name, 'report'])
    custom_not_filter = [{'term': {"bet_order_user_type": 1}}]
    dynamic_argument_dct = None
    if not disable_global_aggregate:
        report_template = get_report_template(start_time, interval_type)
        report_template.update(
            UserReportCreator.create_user_report(
                start_time=start_time, end_time=end_time, event_rule=event_rule,
                index=index, custom_not_filter=custom_not_filter, dynamic_argument_dct=dynamic_argument_dct
            )
        )
        report_template.update({event_rule.get('group_by').replace('.keyword', ''): 'all'})
        insert_or_update(report_template, database=index, collection=collection)
    recharge_reports = UserReportCreator.create_user_report(
        start_time=start_time, end_time=end_time, event_rule=event_rule, index=index,
        custom_not_filter=custom_not_filter, dynamic_argument_dct=dynamic_argument_dct, to_group=True)
    for report in recharge_reports['list']:
        report_id = '-'.join([report[event_rule.get('group_by').replace('.keyword', '')],
                              day, interval_type.value])
        report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
        report_template.update(report)
        insert_or_update(report_template, database=index, collection=collection)


def op_withdraw_group_by_report_handler(interval_type, base_time, last_window, event_name, event_rule, index):
    """
    :param interval_type: 报表时间单位
    :param base_time: 报表时间
    :param last_window: 时间段偏移值
    :param event_name: 报表名
    :param event_rule: 报表配置
    :param index: 商户索引名
    :return: None
    """
    start_time, end_time = get_interval_end_pair(interval_type, base_time, last_window)
    day = str(start_time).split(' ')[0] if interval_type.value == 'day' else str(start_time).split(':')[0]
    user_pool = None
    _create_withdraw_report(index, start_time, end_time, event_rule, interval_type, event_name, user_pool, day)

    for key in WITHDRAW_SUB_TYPE.keys():
        custom_filter = [{"term": {"_withdraw_sub_type.keyword": key}}]
        _create_withdraw_report(index, start_time, end_time, event_rule, interval_type, event_name,
                                user_pool, day, custom_filter=custom_filter, withdraw_sub_type=key)


def _create_withdraw_report(index, start_time, end_time, event_rule, interval_type, event_name, user_pool, day,
                            custom_filter=None, withdraw_sub_type=None):
    sub_type = withdraw_sub_type if withdraw_sub_type else "all"
    collection = '_'.join(['op', event_name, 'report'])
    report_id = '-'.join([sub_type, 'all', day, interval_type.value])
    report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
    report_template.update(dict(sub_type=sub_type))
    report_template.update(
        UserReportCreator.create_user_report(
            start_time=start_time, end_time=end_time, event_rule=event_rule,
            index=index, custom_filter=custom_filter, user_pool=user_pool
        )
    )
    report_template.update({event_rule.get('group_by').replace('.keyword', ''): 'all'})
    insert_or_update(report_template, database=index, collection=collection)
    recharge_reports = UserReportCreator.create_user_report(
        start_time=start_time, end_time=end_time, event_rule=event_rule, index=index,
        custom_filter=custom_filter, to_group=True, user_pool=user_pool)
    for report in recharge_reports['list']:
        report_id = '-'.join([sub_type, report[event_rule.get('group_by').replace('.keyword', '')],
                              day, interval_type.value])
        report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
        report_template.update(dict(sub_type=sub_type))
        report_template.update(report)
        insert_or_update(report_template, database=index, collection=collection)


def op_user_group_by_report_handler(interval_type, base_time, last_window, event_name, event_rule, index):
    """
     :param interval_type: 报表时间单位
     :param base_time: 报表时间
     :param last_window: 时间段偏移值
     :param event_name: 报表名
     :param event_rule: 报表配置
     :param index: 商户索引名
     :return: None
     """
    start_time, end_time = get_interval_end_pair(interval_type, base_time, last_window)
    day = str(start_time).split(' ')[0] if interval_type.value == 'day' else str(start_time).split(':')[0]
    collection = '_'.join(['op', event_name, 'report'])
    custom_not_filter = [{'term': {"bet_order_user_type": 1}}]
    dynamic_argument_dct = _get_op_report_dynamic_argument_dct(
        index, start_time, end_time, custom_not_filter=custom_not_filter
    )
    report_template = get_report_template(start_time, interval_type)
    report_template.update(
        UserReportCreator.create_user_report(
            start_time=start_time, end_time=end_time, event_rule=event_rule, index=index,
            custom_not_filter=custom_not_filter, dynamic_argument_dct=dynamic_argument_dct,
        )
    )
    report_template.update({event_rule.get('group_by').replace('.keyword', ''): 'all'})
    report_template['_chn_device_type'] = "all"
    insert_or_update(report_template, database=index, collection=collection)
    for key in CHN_DEVICE_TYPE.keys():
        report_id = '-'.join([key, day, interval_type.value])
        report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
        custom_filter = [{"term": {"_chn_device_type.keyword": key}}]
        op_user_report = UserReportCreator.create_user_report(
            start_time=start_time, end_time=end_time, event_rule=event_rule, index=index,
            custom_filter=custom_filter, custom_not_filter=custom_not_filter, dynamic_argument_dct=dynamic_argument_dct
        )
        report_template.update(op_user_report)
        report_template.update({event_rule.get('group_by').replace('.keyword', ''): 'all'})
        report_template['_chn_device_type'] = key
        insert_or_update(report_template, database=index, collection=collection)
    recharge_reports = UserReportCreator.create_user_report(
        start_time=start_time, end_time=end_time, event_rule=event_rule, index=index,
        custom_not_filter=custom_not_filter, dynamic_argument_dct=dynamic_argument_dct, to_group=True)
    for report in recharge_reports['list']:
        report_id = '-'.join([report[event_rule.get('group_by').replace('.keyword', '')],
                              day, interval_type.value])
        report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
        report_template.update(report)
        report_template['_chn_device_type'] = "ios" if report['_chn'].startswith("ios_") else "android"
        insert_or_update(report_template, database=index, collection=collection)


def _get_op_report_dynamic_argument_dct(index, start_time, end_time, custom_filter=None,
                                        custom_not_filter=None):
    # 当日充值账号
    user_filter = UserFilter(merchant_name=index)
    user_filter.event_user_filter('recharge', start_time, end_time, custom_filter=custom_filter,
                                  custom_not_filter=custom_not_filter)
    today_recharge_user_pool = user_filter.get_user_pool()
    # 当日充值账号之前充值过的账号
    user_filter = UserFilter(merchant_name=index, user_pool=today_recharge_user_pool)
    user_filter.event_user_filter('recharge', start_time - timedelta(days=3650), start_time,
                                  custom_filter=custom_filter, custom_not_filter=custom_not_filter)
    old_today_recharge_user_pool = user_filter.get_user_pool()
    first_recharge_user_pool = list(set(today_recharge_user_pool) - set(old_today_recharge_user_pool))
    # 当日活跃且之前绑定过的账号
    user_filter = UserFilter(merchant_name=index)
    user_filter.event_user_filter(['bet_order', 'active', 'register', 'recharge', 'withdraw'], start_time, end_time,
                                  custom_filter=custom_filter, custom_not_filter=custom_not_filter)
    active_user_pool = user_filter.get_user_pool()
    user_filter = UserFilter(merchant_name=index, user_pool=active_user_pool)
    user_filter.event_user_filter('bind', start_time - timedelta(days=3650), end_time,
                                  custom_filter=custom_filter, custom_not_filter=custom_not_filter)
    active_bind_user_pool = user_filter.get_user_pool()
    # 当日投注且之前绑定过的账号
    user_filter = UserFilter(merchant_name=index)
    user_filter.event_user_filter('bet_order', start_time, end_time, custom_filter=custom_filter,
                                  custom_not_filter=custom_not_filter)
    bet_order_user_pool = user_filter.get_user_pool()
    user_filter = UserFilter(merchant_name=index, user_pool=bet_order_user_pool)
    user_filter.event_user_filter('bind', start_time - timedelta(days=3650), end_time, custom_filter=custom_filter,
                                  custom_not_filter=custom_not_filter)
    bet_order_bind_user_pool = user_filter.get_user_pool()
    dynamic_target_users_dct = dict(
        first_recharge_user_pool=first_recharge_user_pool,
        active_bind_user_pool=active_bind_user_pool,
        bet_order_bind_user_pool=bet_order_bind_user_pool

    )
    return dynamic_target_users_dct
